Skip to content

Conversation

@kraftp
Copy link
Member

@kraftp kraftp commented Nov 20, 2025

Patching is a mechanism for safely upgrading workflow code. It is an alternative to workflow versioning (though they can be used together).

The problem patching solves is "How do I make a breaking change to a workflow's code but continue execution of long-running workflows that started on the old code version?" A breaking change is any change in what steps run or the order in which they run.

To use patching, first enable it in configuration:

config: DBOSConfig = {
    "name": "dbos-starter",
    "system_database_url": os.environ.get("DBOS_SYSTEM_DATABASE_URL"),
    "enable_patching": True,
}
DBOS(config=config)

Next, when making a breaking change, use an if DBOS.patch(): conditional. DBOS.patch() returns True for new workflows (those started after the breaking change) and False for old workflows (those started before the breaking change). Therefore, if DBOS.patch() is true, call the new code, else call the old code.

So let's say our workflow is:

@DBOS.workflow()
def workflow():
  foo()
  bar()

We want to replace the call to foo() with a call to baz(), which is a breaking change. We can do this safely using a patch:

@DBOS.workflow()
def workflow():
  if DBOS.patch("use-baz"):
    baz()
  else:
    foo()
  bar()

Now, new workflows will run baz(), while old workflows will safely recover through foo().

Once all workflows of the pre-patch code version are complete, we can remove patches from our code. First, we deprecate the patch. This will safely run workflows containing the patch marker, but will not insert the patch marker into new workflows:

@DBOS.workflow()
def workflow():
  DBOS.deprecate_patch("use-baz")
  baz()
  bar()

Then, when all workflows containing the patch marker are complete, we can remove the patch entirely and complete the workflow upgrade!

@DBOS.workflow()
def workflow():
  baz()
  bar()

If any mistakes happen during the process (a breaking change is not patched, or a patch is deprecated or removed prematurely), the workflow will throw a clean DBOSUnexpectedStepError pointing to the step where the problem occurred.

Also, one advanced feature is that if you need to make consecutive breaking changes to the same code, you can stack patches:

@DBOS.workflow()
def workflow():
  if DBOS.patch("use-qux"):
    qux()
  elif DBOS.patch("use-baz"):
    baz()
  else:
    foo()
  bar()

@kraftp kraftp marked this pull request as ready for review November 21, 2025 01:09
@dosubot
Copy link

dosubot bot commented Nov 21, 2025

Related Documentation

Checked 8 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

@maxdml
Copy link
Contributor

maxdml commented Nov 21, 2025

How would I use this patching system to fix a workflow? Manually fork from the step before the patch?

@kraftp kraftp merged commit 95d0df9 into main Dec 8, 2025
10 checks passed
@kraftp kraftp deleted the kraftp/patching branch December 8, 2025 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants